var Fastbox = (function(){

	function Fastbox(links, path_css, path_php){
		// We will need this
		new Asset.css(path_css);

		// Apply lightbox on the links elements
		$$(links).each(function(link){
			link.addEvent('click', function(e){
				e.stop();

				// ===============
				// = GLOBAL VARS =
				// ===============
				var img, loading, closed, timer, block, fix_hud, img_width, img_height;

				// ===================
				// = BUILD INTERFACE =
				// ===================

				// OVERLAY
				if (!overlay) {
					var overlay = new Element('div', {'id': 'overlay'});
					// --- Effects
					var fx_o = new Fx.Morph(overlay, {'duration': 500, 'link': 'cancel'});
					// --- Events
					overlay.addEvent('click', function(){ close(); });
				}
				// --- Inject
				fx_o.set({'opacity': 0});
				overlay.inject(document.body);

				// IMAGE FRAME
				if (!frame) {
					var frame = new Element('div', {'id': 'frame'});
					// --- Events
					frame.addEvent('click', function(){ close(); });
				}
				// --- Inject
				frame.inject(document.body);

				// INDICATOR
				if (!indicator){
					var indicator = new Element('div', {'id': 'indicator'});
					var busy = new Element('div', {'id': 'busy'}).inject(indicator);
					// --- Events
					indicator.addEvent('click', function(){ close(); });
				}

				// HUD CONTROLLER
				if (!hud) {
					var c_prev = new Element('a', {'id': 'c_prev'});
					var c_down = new Element('a', {'id': 'c_down'});
					var c_next = new Element('a', {'id': 'c_next'});
					var controls = new Elements([c_prev, c_down, c_next]);
					var hud = new Element('div', {'id': 'hud'}).adopt(controls);
					// --- Effects
					var fx = new Fx.Morph(hud, {'duration': 500, 'link': 'cancel'});
					fx.addEvent('onComplete', function(){
						block = false;
						if (fix_hud) return;
						if (hud.getStyle('opacity') === 1) {
							timer = fx.start.delay(1000, fx, {'opacity': 0});
						}
					});
					// --- Events
					controls.addEvent('mouseenter', function(){
						$clear(timer);
						fix_hud = true;
					})
					controls.addEvent('mouseout', function(){
						fix_hud = false;
						timer = fx.start.delay(1000, fx, {'opacity': 0});
					});
					c_next.addEvent('click', function(){ change_img('next', c_next); });
					c_prev.addEvent('click', function(){ change_img('prev', c_prev); });
				}
				// --- Inject
				fx.set({'opacity': 0});
				hud.inject(document.body);

				// DOCUMENT EVENTS
				window.addEvent('mousemove', function(){
					if (block) return;
					block = true;
					$clear(timer);
					fx.start({'opacity': 1});
				});
				document.addEvent('keydown', function(event){
					switch(event.code) {
						case 27:	// Esc
						case 88:	// 'x'
						case 67:	// 'c'
						close();
						break;
						case 40:	// down
						location = path_php+'?img='+link.getProperty('href');
						break;
						case 37:	// Left arrow
						case 80:	// 'p'
						change_img('prev', c_prev);
						break;	
						case 39:	// Right arrow
						case 78:	// 'n'
						change_img('next', c_next);
					}
				});

				// ======================
				// = INTERACTIVE EVENTS =
				// ======================

				// CLOSING EVENT
				function close(){
					closed = true;
					if (indicator) indicator.dispose();
					frame.dispose();
					hud.dispose();
					fx_o.start({'opacity': 0}).chain(function(){
						overlay.dispose();
					});
					document.removeEvents('keydown');
					window.removeEvents('mousemove');
					window.removeEvents('resize');
				}

				// UPDATE HUD, AND PRELOAD
				function update(){
					// Test prev/next images
					if (link.getParent().getNext()) {
						c_next.removeClass('inactive');
						// Preloading
						new Asset.image(link.getParent().getNext().getFirst().getProperty('href'));
					}
					else {
						c_next.addClass('inactive');
					}
					if (link.getParent().getPrevious()) {
						c_prev.removeClass('inactive');
						// Preloading
						new Asset.image(link.getParent().getPrevious().getFirst().getProperty('href'));
					}
					else {
						c_prev.addClass('inactive');
					}
					// Set the HREF for the download controller
					c_down.setProperty('href', path_php+'?img='+link.getProperty('href'));
				}

				// IMAGE IS READY
				function img_ready(){
					loading = false;
					if (closed) return;
					// Timeout pour firefox qui fait un glitch visuel sinon
					setTimeout(function(){ indicator.dispose(); }, 100);
					img.inject(frame);
					img_width = img.getSize().x;
					img_height = img.getSize().y;
					resize_img();
				}

				// PREV/NEXT IMAGES CALL
				function change_img(to, button){
					if (button.hasClass('inactive')) return;
					img.dispose();
					if (!$('busy')) indicator.grab(busy);
					indicator.removeClass('error').inject(document.body);
					// Update HUD
					if (to == "next") {
						link = link.getParent().getNext().getFirst();
					}
					else {
						link = link.getParent().getPrevious().getFirst();
					}
					update();
					// Do the asset now
					loading = true;
					img = new Asset.image(link.getProperty('href'), {
						'title': link.getProperty('title'),
						'alt': link.getProperty('title'),
						'onerror': function(){
							indicator.empty().setProperty('class', 'error');
						},
						'onload': function(){
							img_ready();
						}
					});
				}

				// RESIZE IMAGE
				function resize_img(){
					// Get some informations
					var win_width = window.getSize().x;
					var win_height = window.getSize().y;

					var ratio = img_width / img_height;
					var height; var width;

					// Resizing function
					function resize(dimension){
						if (dimension == "x") {
							width = win_width - 20;
							height = width / ratio;
						}
						else {
							height = win_height - 20;
							width = height * ratio;
						}
					}

					// Let's do the tests
					if (win_width >= img_width) {
						// Pas tronquée
						if (win_height >= img_height) {
							width = img_width;
							height = img_height;
						}
						// Tronquée en hauteur
						else {
							resize('y');
						}
					}
					else {
						// Tronquée en largeur
						if (win_height >= img_height) {
							resize('x');
						}
						// Tronquée en hauteur & largeur
						else {
							// Fenêtre en portrait
							if (win_width < win_height) {
								// Image en paysage ou en carré
								if (ratio >= 1) {
									resize('x');
								}
								// Image en portrait
								else if (ratio < 1) {
									// Image plus rapidement redimensionnée en hauteur qu'en largeur
									if (img_width - win_width > img_height - win_height) {
										resize('y');
									}
									// Inversement
									else {
										resize('x');
									}
								}
							}
							// Fenêtre en paysage
							else {
								// Image en paysage
								if (ratio > 1) {
									// Image plus rapidement redimensionnée en hauteur qu'en largeur
									if (img_width - win_width > img_height - win_height) {
										resize('x');
									}
									// Inversement
									else {
										resize('y');
									}
								}
								// Image en portrait ou en carré
								else if (ratio <= 1) {
									resize('y');
								}
							}
						}
					}
					// POSITION : TOP & LEFT
					var left = (win_width - width) / 2;
					var top = (win_height - height) / 2;
					// SET THE STYLES
					img.setProperties({'width': width, 'height': height});
					img.set('style', 'top:'+top+'px;left:'+left+'px');
				}

				// ==================
				// = FIRST SEQUENCE =
				// ==================

				// DEPLOY OVERLAY
				fx_o.start({'opacity': 0.8}).chain(function(){
					if (!loading) return;
					indicator.inject(document.body);
				});

				// LOAD FIRST IMAGE
				loading = true;
				img = new Asset.image(this.getProperty('href'), {
					'title': this.getProperty('title'),
					'alt': this.getProperty('title'),
					'onerror': function(){
						indicator.empty().setProperty('class', 'error');
					},
					'onload': function(){
						img_ready();
						window.addEvent('resize', function(){
							resize_img();
						});
					}
				});

				// UPDATE HUD
				update();
			});
		});
	}

	return Fastbox;  
})();